<?php

require_once(__DIR__ . "/BaseSafeChecker.php");

class AntiProxy extends BaseSafeChecker
{

    private $trapPageExpression = "";     // 蜜罐陷阱页面的表达式 like */contract/*.php
    private $ptrCheckPageExpression = "";      // 反解检查的页面的表达式 like */contract/*.php
    private $trapPage = "";      // 针对非法用户的重定向页面
    private $mode = "working";


    public function check($ipAddress = "")
    {
        global $_SERVER;

        $name = RequestUtils::get("_name_","NO_NAME");

        $ip = $ipAddress;
        if (empty($ipAddress)) {
            $ip = RequestUtils::getIp();
        }
        $this->debug("{$name} access ip is $ip");

        $page = $_SERVER["SCRIPT_NAME"];
        $isTrapPage = $this->matched($page, $this->trapPageExpression);
        $isCheckPage = $this->matched($page, $this->ptrCheckPageExpression);

        if ($this->ipBlocked($ip)) {
            $this->debug("{$name} $ip is blocked");
            if ($isTrapPage || $isCheckPage) {
                $this->addPageAccessLog($ip, 2);
            }
            $this->redirect();
            return false;
        }
        if ($this->ipOpened($ip)) {
            $this->debug("{$name} $ip is opened");
            if ($isTrapPage || $isCheckPage) {
                $this->addPageAccessLog($ip, 1);
            }
            return true;
        }

        if ($isTrapPage) {
            $this->debug("{$name} $page match trap");
            $this->blockIp($ip);
            $this->addPageAccessLog($ip, 2);
            $this->redirect();
            return false;
        }
        if ($isCheckPage) {
            // 检查ip反解
            $this->debug("{$name} $page is check page");
            $host = $this->getHostName($ip);
            if (empty($host)) {
                $this->debug("{$name} $ip ptr name is null");
                $this->blockIp($ip);
                $this->addPageAccessLog($ip, 2);
                $this->redirect();
                return false;
            }
            if (!$this->isHostNameOpend($host)) {
                $this->debug("{$name} $ip ptr name $host is blocked");
                $this->blockIp($ip);
                $this->addPageAccessLog($ip, 2);
                $this->redirect();
                return false;
            } else {
                // 将ip加入白名单
                $this->openIp($ip);
                $this->addPageAccessLog($ip, 1);
                $this->debug("{$name} $ip has added into white list");
            }
        }
        $this->debug("{$name} $ip 通过所有检测，没有屏蔽");
        return true;
    }


    private function addPageAccessLog($ip, $status_id, $host = "")
    {
        global $_SERVER;
        try {
            $host = $this->getHostName($ip);
            $bean = ["ip" => $ip, "status_id" => $status_id];
            $bean["site_name"] = $_SERVER["HTTP_HOST"];
            $bean["host"] = $host;
            $bean["page_url"] = $_SERVER["SCRIPT_NAME"];
            $bean["created_at"] = date('Y-m-d H:i:s');
            $sql = SqlMaker::make_insert("anti_proxy_logs", $bean);
            DBUtils::db_insert($sql, $this->getDbId());
        } catch (\Exception $e) {

        }
    }


    private function redirect()
    {
        if ($this->mode === "checking") {
            echo "redirect 关闭...";
            return;
        }
        $url = $this->trapPage;
        if (empty($url)) {
            $url = "http://news.163.com/";
        }
        header("location: $url");
    }


    public function setModeToChecking()
    {
        $this->mode = "checking";
    }

    /**
     * @return string
     */
    public function getTrapPageExpression()
    {
        return $this->trapPageExpression;
    }

    /**
     * @param string $trapPageExpression
     */
    public function setTrapPageExpression($trapPageExpression)
    {
        $this->trapPageExpression = $trapPageExpression;
    }

    /**
     * @return string
     */
    public function getPtrCheckPageExpression()
    {
        return $this->ptrCheckPageExpression;
    }

    /**
     * @param string $ptrCheckPageExpression
     */
    public function setPtrCheckPageExpression($ptrCheckPageExpression)
    {
        $this->ptrCheckPageExpression = $ptrCheckPageExpression;
    }

    /**
     * @return string
     */
    public function getTrapPage()
    {
        return $this->trapPage;
    }

    /**
     * @param string $trapPage
     */
    public function setTrapPage($trapPage)
    {
        $this->trapPage = $trapPage;
    }


}